#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
评估管理模块

提供对话数据提取、格式化和评估功能。
"""

import json
import os
import pathlib
from typing import Any, Dict, List, Optional, Tuple

from core.utils.log import mylogger


def extract_character_profile(character_config_path: str) -> Dict[str, Any]:
    """从角色配置文件中提取角色信息

    Args:
        character_config_path: 角色配置文件路径

    Returns:
        Dict: 包含角色信息的字典
    """
    try:
        with open(character_config_path, "r", encoding="utf-8") as f:
            character_config = json.load(f)

        # 提取角色基本信息，支持中文键名
        character_profile = {
            "name": character_config.get("name", character_config.get("姓名", "")),
            "age": character_config.get("age", character_config.get("年龄", "")),
            "gender": character_config.get("gender", character_config.get("性别", "")),
            "personality": character_config.get(
                "personality", character_config.get("性格", "")
            ),
        }

        return character_profile

    except Exception as e:
        mylogger.error(f"提取角色信息失败: {e}")
        return {}


def extract_dialogue_data(dialogue_file_path: str) -> List[Dict[str, Any]]:
    """从对话文件中提取对话数据

    Args:
        dialogue_file_path: 对话文件路径

    Returns:
        List[Dict]: 对话数据列表
    """
    try:
        with open(dialogue_file_path, "r", encoding="utf-8") as f:
            dialogue_data = json.load(f)

        # 确保数据是列表格式
        if not isinstance(dialogue_data, list):
            mylogger.error(f"对话数据格式错误: {dialogue_file_path}")
            return []

        return dialogue_data

    except Exception as e:
        mylogger.error(f"提取对话数据失败: {e}")
        return []


def extract_attitude_status(
    scenario_file_path: str, round_index: int
) -> Dict[str, Any]:
    """从场景文件中提取指定回合的态度状态

    Args:
        scenario_file_path: 场景文件路径
        round_index: 回合索引

    Returns:
        Dict: 态度状态字典
    """
    try:
        with open(scenario_file_path, "r", encoding="utf-8") as f:
            scenario_data = json.load(f)

        if not isinstance(scenario_data, list):
            mylogger.error(f"场景数据格式错误，预期为列表: {scenario_file_path}")
            return {}
        # 提取指定回合的态度状态
        if round_index < 0 or round_index >= len(scenario_data):
            mylogger.error(
                f"回合索引超出范围: {round_index}, 总回合数: {len(scenario_data)}"
            )
            return {}

        round_data = scenario_data[round_index]

        # 提取状态信息
        attitude_status = {
            "status": round_data.get("status", ""),
            "scene": round_data.get("scene", ""),
            "extra": round_data.get("extra", ""),
        }

        return attitude_status

    except Exception as e:
        mylogger.error(f"提取态度状态失败: {e}")
        return {}


def generate_formatted_dialogue(
    character_profile: Dict[str, Any],
    dialogue_data: List[Dict[str, Any]],
    scenario_file_path: str,
) -> Dict[str, Any]:
    """生成格式化的对话数据

    Args:
        character_profile: 角色信息
        dialogue_data: 对话数据
        scenario_file_path: 场景文件路径，用于动态获取每轮的态度状态

    Returns:
        Dict: 格式化的对话数据
    """
    try:
        # 将对话数据转换为符合 eval_prompt.py 中定义的格式
        dialogue_rounds = []
        scene_info = ""  # 用于存储场景信息

        for i, dialogue in enumerate(dialogue_data):
            # 动态获取当前轮次的态度状态
            attitude_status = extract_attitude_status(scenario_file_path, i)

            # 获取当前轮次的态度信息
            current_attitude = (
                attitude_status.get("status", "")
                + "\n"
                + attitude_status.get("extra", "")
            )

            # 保存场景信息（使用第一轮的场景信息）
            if i == 0:
                scene_info = attitude_status.get("scene", "")

            dialogue_round = {
                "round": dialogue.get("id", i + 1),
                "current_attitude": current_attitude,
                "user_input": dialogue.get("input", ""),
                "model_1_output": dialogue.get("doubaoFlash_output", ""),
                "model_2_output": dialogue.get("doubaoPro_output", ""),
            }
            dialogue_rounds.append(dialogue_round)

        # 构建格式化的对话数据
        formatted_dialogue = {
            "character_profile": character_profile,
            "dialogue_rounds": dialogue_rounds,
            "metadata": {
                "total_rounds": len(dialogue_data),
                "timestamp": (
                    dialogue_data[-1].get("timestamp", "") if dialogue_data else ""
                ),
                "scene": scene_info,
            },
        }

        return formatted_dialogue

    except Exception as e:
        mylogger.error(f"生成格式化对话数据失败: {e}")
        return {}


def save_formatted_dialogue(
    formatted_dialogue: Dict[str, Any], output_path: str
) -> bool:
    """保存格式化的对话数据

    Args:
        formatted_dialogue: 格式化的对话数据
        output_path: 输出文件路径

    Returns:
        bool: 是否成功保存
    """
    try:
        # 确保输出目录存在
        os.makedirs(os.path.dirname(output_path), exist_ok=True)

        # 保存格式化的对话数据
        with open(output_path, "w", encoding="utf-8") as f:
            json.dump(formatted_dialogue, f, ensure_ascii=False, indent=2)

        mylogger.info(f"已保存格式化对话数据: {output_path}")
        return True

    except Exception as e:
        mylogger.error(f"保存格式化对话数据失败: {e}")
        return False


class EvalManager:
    """评估管理器，提供对话数据处理和评估功能"""

    def __init__(self, llm=None, output_dir: str = "data", temperature: float = 0.1):
        self.llm = llm
        self.output_dir = output_dir
        self.temperature = temperature

        # 确保输出目录存在
        os.makedirs(output_dir, exist_ok=True)

        mylogger.info(f"EvalManager initialized with output_dir: {output_dir}")

    async def evaluate_dialogue(
        self, character_file_path: str, result_file_path: str, scenario_file_path: str
    ) -> str:
        """执行对话评估

        Args:
            character_file_path: 角色配置文件路径
            result_file_path: 对话结果文件路径
            scenario_file_path: 场景配置文件路径

        Returns:
            评估结果字符串
        """
        try:
            mylogger.info("开始执行对话评测...")

            # 准备评测数据
            character_profile = extract_character_profile(character_file_path)
            dialogue_data = extract_dialogue_data(result_file_path)
            formatted_data = generate_formatted_dialogue(
                character_profile, dialogue_data, scenario_file_path
            )

            # 执行评测
            from core.prompts.eval_prompt import SYSTEM_PROMPT

            system_message = {"role": "system", "content": SYSTEM_PROMPT}
            user_message = {
                "role": "user",
                "content": json.dumps(formatted_data, ensure_ascii=False, indent=2),
            }
            messages = [system_message, user_message]

            mylogger.info(f"评测消息: {messages}")

            # 调用LLM进行评测
            response = await self.llm.chat(messages, temperature=self.temperature)
            mylogger.info(f"评测响应: {response}")

            # 保存评测结果
            await self._save_evaluation_result(response)

            mylogger.info("对话评测完成")
            return response

        except Exception as e:
            mylogger.error(f"评测过程中出错: {e}")
            raise

    async def _save_evaluation_result(self, result: str) -> None:
        """保存评测结果"""
        output_file_path = os.path.join(self.output_dir, "evaluation_result.json")

        try:
            with open(output_file_path, "w", encoding="utf-8") as f:
                if isinstance(result, str):
                    try:
                        result_dict = json.loads(result)
                        json.dump(result_dict, f, ensure_ascii=False, indent=2)
                    except json.JSONDecodeError:
                        f.write(result)

            mylogger.info(f"评测结果已保存到: {output_file_path}")

        except Exception as e:
            mylogger.error(f"保存评测结果时出错: {e}")
            raise

    def process_dialogue(
        self,
        character_config_path: str,
        dialogue_file_path: str,
        scenario_file_path: str,
        round_index: int,
        output_path: Optional[str] = None,
    ) -> Tuple[Dict[str, Any], str]:
        """处理对话数据并生成格式化输出

        Args:
            character_config_path: 角色配置文件路径
            dialogue_file_path: 对话文件路径
            scenario_file_path: 场景文件路径
            round_index: 回合索引
            output_path: 输出文件路径，如果为None则自动生成

        Returns:
            Tuple[Dict, str]: 格式化的对话数据和输出路径
        """
        # 提取所需数据
        character_profile = extract_character_profile(character_config_path)
        dialogue_data = extract_dialogue_data(dialogue_file_path)

        # 生成格式化对话数据，传入scenario_file_path以便动态获取每轮的态度状态
        formatted_dialogue = generate_formatted_dialogue(
            character_profile, dialogue_data, scenario_file_path
        )

        # 如果未指定输出路径，则自动生成
        if output_path is None:
            character_name = character_profile.get("name", "unknown")
            output_path = os.path.join(
                self.output_dir, f"{character_name}_dialogue_round_{round_index}.json"
            )

        # 保存格式化对话数据
        save_formatted_dialogue(formatted_dialogue, output_path)

        return formatted_dialogue, output_path
